/**
 * Copyright 2014 National University of Ireland, Galway.
 *
 * This file is part of the SIREn project. Project and contact information:
 *
 *  https://github.com/rdelbru/SIREn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sindice.siren.qparser.keyword.processors;

import org.apache.lucene.queryparser.flexible.core.config.QueryConfigHandler;
import org.apache.lucene.queryparser.flexible.core.processors.NoChildOptimizationQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.core.processors.QueryNodeProcessorPipeline;
import org.apache.lucene.queryparser.flexible.core.processors.RemoveDeletedQueryNodesProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.AllowLeadingWildcardProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.BooleanSingleChildOptimizationQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.BoostQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.DefaultPhraseSlopQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.FuzzyQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.LowercaseExpandedTermsQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.MultiFieldQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.OpenRangeQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.PhraseSlopQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.RemoveEmptyNonLeafQueryNodeProcessor;
import org.apache.lucene.queryparser.flexible.standard.processors.StandardQueryNodeProcessorPipeline;
import org.apache.lucene.queryparser.flexible.standard.processors.TermRangeQueryNodeProcessor;
import org.apache.lucene.search.Query;
import org.sindice.siren.qparser.keyword.KeywordSyntaxParser;
import org.sindice.siren.qparser.keyword.builders.KeywordQueryTreeBuilder;
import org.sindice.siren.qparser.keyword.config.KeywordQueryConfigHandler;
import org.sindice.siren.search.node.TwigQuery;

/**
 * This pipeline has all the processors needed to process a query node tree,
 * generated by {@link KeywordSyntaxParser}, already assembled.
 *
 * <p>
 *
 * The order they are assembled affects the results.
 *
 * <p>
 *
 * This processor pipeline was designed to work with
 * {@link KeywordQueryConfigHandler}.
 *
 * <p>
 *
 * The result query node tree can be used to build a {@link Query} object using
 * {@link KeywordQueryTreeBuilder}.
 *
 * <p>
 *
 * This is a modification of the original
 * {@link StandardQueryNodeProcessorPipeline} which adds a
 * {@link ChangeDefaultOperatorNodeProcessor} in order to correctly support
 * unary operators (SRN-106). Furthermore, it removes the field expansion
 * {@link MultiFieldQueryNodeProcessor}, and also the {@link BoostQueryNodeProcessor}
 * since it considers fields (GH-75). Several {@link QueryNodeProcessor} were
 * added to the {@link TwigQuery} syntax of the {@link KeywordSyntaxParser}.
 *
 * @see KeywordQueryTreeBuilder
 * @see KeywordQueryConfigHandler
 * @see KeywordSyntaxParser
 */
public class KeywordQueryNodeProcessorPipeline
extends QueryNodeProcessorPipeline {

  public KeywordQueryNodeProcessorPipeline(final QueryConfigHandler queryConfig) {
    super(queryConfig);

    this.add(new TopLevelQueryNodeProcessor());
    this.add(new AllowTwigProcessor());
    this.add(new WildcardNodeQueryNodeProcessor());
    this.add(new RootLevelTwigQueryNodeProcessor());
    this.add(new ChangeDefaultOperatorNodeProcessor());
    this.add(new WildcardQueryNodeProcessor());
    this.add(new FuzzyQueryNodeProcessor());
    this.add(new QNamesProcessor());
    this.add(new PhraseQueryNodeProcessor());
    this.add(new DatatypeQueryNodeProcessor());
    // Ranges
    this.add(new OpenRangeQueryNodeProcessor());
    // this processor creates a NodeNumericRangeQuery from a FieldQueryNode,
    // with both bounds equal. This is why it is before DatatypeAnalyzerProcessor
    this.add(new NodeNumericQueryNodeProcessor());
    this.add(new NodeNumericRangeQueryNodeProcessor());
    this.add(new TermRangeQueryNodeProcessor());
    this.add(new LowercaseExpandedTermsQueryNodeProcessor());
    this.add(new DatatypeAnalyzerProcessor());
    this.add(new PhraseSlopQueryNodeProcessor());
    this.add(new DefaultPhraseSlopQueryNodeProcessor());

    this.add(new AllowFuzzyAndWildcardProcessor());
    this.add(new AllowLeadingWildcardProcessor());

    this.add(new GroupQueryNodeProcessor());
    /*
     * TODO GroupQueryNodeProcessor is deprecated in Lucene4.0 in favour to
     * BooleanQuery2ModifierNodeProcessor. Try to apply changes done in SIREn
     * to it.
     */
//    add(new BooleanQuery2ModifierNodeProcessor());
    this.add(new NoChildOptimizationQueryNodeProcessor());
    this.add(new RemoveDeletedQueryNodesProcessor());
    this.add(new RemoveEmptyNonLeafQueryNodeProcessor());
    this.add(new BooleanSingleChildOptimizationQueryNodeProcessor());
    this.add(new MultiNodeTermRewriteMethodProcessor());
    this.add(new NodeBooleanQueryNodeProcessor());
    this.add(new NotSupportedQueryProcessor());
  }

}
